if {"::tcltest" ni [namespace children]} {
	package require tcltest
	namespace import ::tcltest::*
}

package require rl_json
namespace path {::rl_json}

test keys-0.1 {too few args} -body { #<<<
	set code [catch {
		json keys
	} r o]
	list $code $r [dict get $o -errorcode]
} -cleanup {
	unset -nocomplain code r o
} -result {1 {wrong # args: should be "*keys json_val ?path ...?"} {TCL WRONGARGS}} -match glob
#>>>
test keys-1.1 {type: object, no path} -body { #<<<
	json keys {
		{
			"foo": "bar",
			"baz":  ["str", 123, 123.4, true, false, null, {"inner": "obj"}]
		}
	}
} -result {foo baz}
#>>>
test keys-1.2 {type: array, no path} -body { #<<<
	json keys {
		[1,2,3]
	}
} -returnCodes error -result {Named JSON value type isn't supported: array}
#>>>
test keys-1.3 {type: string, no path} -body { #<<<
	json keys {
		"foo"
	}
} -returnCodes error -result {Named JSON value type isn't supported: string}
#>>>
test keys-1.4 {type: number, no path} -body { #<<<
	set code [catch {
		json keys {
			1234
		}
	} r o]
	list $code $r [dict get $o -errorcode]
} -cleanup {
	unset -nocomplain code r o
} -result {1 {Named JSON value type isn't supported: number} NONE}
#>>>
test keys-1.5 {type: boolean true, no path} -body { #<<<
	set code [catch {
		json keys {
			true
		}
	} r o]
	list $code $r [dict get $o -errorcode]
} -cleanup {
	unset -nocomplain code r o
} -result {1 {Named JSON value type isn't supported: boolean} NONE}
#>>>
test keys-1.6 {type: boolean false, no path} -body { #<<<
	set code [catch {
		json keys {
			false
		}
	} r o]
	list $code $r [dict get $o -errorcode]
} -cleanup {
	unset -nocomplain code r o
} -result {1 {Named JSON value type isn't supported: boolean} NONE}
#>>>
test keys-1.7 {type: null, no path} -body { #<<<
	set code [catch {
		json keys {
			null
		}
	} r o]
	list $code $r [dict get $o -errorcode]
} -cleanup {
	unset -nocomplain code r o
} -result {1 {Named JSON value type isn't supported: null} NONE}
#>>>
test keys-2.1 {type: object, path} -body { #<<<
	json keys {
		{
			"foo": "bar",
			"baz":  ["str", 123, 123.4, true, false, null, {"inner": "obj", "key2": "foo"}]
		}
	} baz end
} -result {inner key2}
#>>>
test keys-2.2 {type: array, path} -body { #<<<
	json keys {
		{
			"foo": "bar",
			"baz":  ["str", 123, 123.4, true, false, null, {"inner": "obj"}]
		}
	} baz
} -returnCodes error -result {Named JSON value type isn't supported: array}
#>>>
test keys-2.3 {type: string, path} -body { #<<<
	json keys {
		{
			"foo": "bar",
			"baz":  ["str", 123, 123.4, true, false, null, {"inner": "obj"}]
		}
	} foo
} -returnCodes error -result {Named JSON value type isn't supported: string}
#>>>
test keys-2.4 {type: number, path} -body { #<<<
	set code [catch {
		json keys {
			{
				"foo": "bar",
				"baz":  ["str", 123, 123.4, true, false, null, {"inner": "obj"}]
			}
		} baz 2
	} r o]
	list $code $r [dict get $o -errorcode]
} -result {1 {Named JSON value type isn't supported: number} NONE}
#>>>
test keys-2.5 {type: boolean true, path} -body { #<<<
	set code [catch {
		json keys {
			{
				"foo": "bar",
				"baz":  ["str", 123, 123.4, true, false, null, {"inner": "obj"}]
			}
		} baz 3
	} r o]
	list $code $r [dict get $o -errorcode]
} -result {1 {Named JSON value type isn't supported: boolean} NONE}
#>>>
test keys-2.6 {type: boolean false, path} -body { #<<<
	set code [catch {
		json keys {
			{
				"foo": "bar",
				"baz":  ["str", 123, 123.4, true, false, null, {"inner": "obj"}]
			}
		} baz 4
	} r o]
	list $code $r [dict get $o -errorcode]
} -result {1 {Named JSON value type isn't supported: boolean} NONE}
#>>>
test keys-2.7 {type: null, path} -body { #<<<
	set code [catch {
		json keys {
			{
				"foo": "bar",
				"baz":  ["str", 123, 123.4, true, false, null, {"inner": "obj"}]
			}
		} baz 5
	} r o]
	list $code $r [dict get $o -errorcode]
} -result {1 {Named JSON value type isn't supported: null} NONE}
#>>>
test keys-3.1 {type: invalid path} -body { #<<<
	set code [catch {
		json keys {
			{
				"foo": "bar",
				"baz":  ["str", 123, 123.4, true, false, null, {"inner": "obj"}]
			}
		} baz 7
	} r o]
	list $code $r [dict get $o -errorcode]
} -result {1 {Named JSON value type isn't supported: null} NONE}
#>>>
test keys-3.2 {type: invalid path: invalid key} -body { #<<<
	set code [catch {
		json keys {
			{
				"foo": "bar",
				"baz":  ["str", 123, 123.4, true, false, null, {"inner": "obj"}]
			}
		} quux
	} r o]
	list $code $r [dict get $o -errorcode]
} -result {1 {Path element 2: "quux" not found} NONE}
#>>>

# Invalid paths
test keys-60.1 {invalid path: missing key} -body { #<<<
	json keys {
		{
			"foo": "bar",
			"baz":  ["str", 123, 123.4, true, false, null, {"inner": "obj"}],
			"something": {
				"?type": "fromdoc"
			}
		}
	} blah
} -returnCodes error -result {Path element 2: "blah" not found}
#>>>
test keys-60.2 {invalid path: subscribed atomic: string} -body { #<<<
	json keys {
		{
			"foo": "bar",
			"baz":  ["str", 123, 123.4, true, false, null, {"inner": "obj"}],
			"something": {
				"?type": "fromdoc"
			}
		}
	} foo blah
} -returnCodes error -result {Cannot descend into atomic type "string" with path element 2: "blah"}
#>>>
test keys-60.3 {invalid path: subscribed atomic: number} -body { #<<<
	json keys {
		{
			"foo": "bar",
			"baz":  ["str", 123, 123.4, true, false, null, {"inner": "obj"}],
			"something": {
				"?type": "fromdoc"
			}
		}
	} baz 1 blah
} -returnCodes error -result {Cannot descend into atomic type "number" with path element 3: "blah"}
#>>>
test keys-60.4 {invalid path: subscribed atomic: boolean} -body { #<<<
	json keys {
		{
			"foo": "bar",
			"baz":  ["str", 123, 123.4, true, false, null, {"inner": "obj"}],
			"something": {
				"?type": "fromdoc"
			}
		}
	} baz 3 blah
} -returnCodes error -result {Cannot descend into atomic type "boolean" with path element 3: "blah"}
#>>>
test keys-60.5 {invalid path: subscribed atomic: null} -body { #<<<
	json keys {
		{
			"foo": "bar",
			"baz":  ["str", 123, 123.4, true, false, null, {"inner": "obj"}],
			"something": {
				"?type": "fromdoc"
			}
		}
	} baz 5 blah
} -returnCodes error -result {Cannot descend into atomic type "null" with path element 3: "blah"}
#>>>
test keys-60.6 {invalid path: invalid array index} -body { #<<<
	json keys {
		{
			"foo": "bar",
			"baz":  ["str", 123, 123.4, true, false, null, {"inner": "obj"}],
			"something": {
				"?type": "fromdoc"
			}
		}
	} baz blah
} -returnCodes error -result {Expected an integer index or end(-integer)?, got blah}
#>>>
test keys-60.7 {invalid path: invalid array index} -body { #<<<
	json keys {
		{
			"foo": "bar",
			"baz":  ["str", 123, 123.4, true, false, null, {"inner": "obj"}],
			"something": {
				"?type": "fromdoc"
			}
		}
	} baz end-12
} -returnCodes error -result {Named JSON value type isn't supported: null}
#>>>
test keys-60.8 {invalid path: invalid array index} -body { #<<<
	json keys {
		{
			"foo": "bar",
			"baz":  ["str", 123, 123.4, true, false, null, {"inner": "obj"}],
			"something": {
				"?type": "fromdoc"
			}
		}
	} baz 100
} -returnCodes error -result {Named JSON value type isn't supported: null}
#>>>
test keys-60.9 {invalid path: invalid array index} -body { #<<<
	json keys {
		{
			"foo": "bar",
			"baz":  ["str", 123, 123.4, true, false, null, {"inner": "obj"}],
			"something": {
				"?type": "fromdoc"
			}
		}
	} baz -2
} -returnCodes error -result {Named JSON value type isn't supported: null}
#>>>
test keys-60.10 {invalid path: invalid array index} -body { #<<<
	json keys {
		{
			"foo": "bar",
			"baz":  ["str", 123, 123.4, true, false, null, {"inner": "obj"}],
			"something": {
				"?type": "fromdoc"
			}
		}
	} baz end-2foo
} -returnCodes error -result {Expected an integer index or end(-integer)?, got end-2foo}
#>>>
test keys-60.11 {invalid path: invalid array index} -body { #<<<
	json keys {
		{
			"foo": "bar",
			"baz":  ["str", 123, 123.4, true, false, null, {"inner": "obj"}],
			"something": {
				"?type": "fromdoc"
			}
		}
	} baz end-foo
} -returnCodes error -result {Expected an integer index or end(-integer)?, got end-foo}
#>>>
test keys-60.12 {invalid path: invalid array index} -body { #<<<
	json keys {
		{
			"foo": "bar",
			"baz":  ["str", 123, 123.4, true, false, null, {"inner": "obj"}],
			"something": {
				"?type": "fromdoc"
			}
		}
	} baz end2
} -returnCodes error -result {Expected an integer index or end(-integer)?, got end2}
#>>>
test keys-60.13 {invalid path: invalid array index} -body { #<<<
	json keys {
		{
			"foo": "bar",
			"baz":  ["str", 123, 123.4, true, false, null, {"inner": "obj"}],
			"something": {
				"?type": "fromdoc"
			}
		}
	} baz end+2
} -returnCodes error -result {Expected an integer index or end(-integer)?, got end+2}
#>>>
test keys-60.14 {invalid path: invalid array index} -body { #<<<
	json keys {
		{
			"foo": "bar",
			"baz":  ["str", 123, 123.4, true, false, null, {"inner": "obj"}],
			"something": {
				"?type": "fromdoc"
			}
		}
	} baz "end- 2"
} -returnCodes error -result {Expected an integer index or end(-integer)?, got end- 2}
#>>>
test keys-60.15 {invalid path: invalid array index} -body { #<<<
	json keys {
		{
			"foo": "bar",
			"baz":  ["str", 123, 123.4, true, false, null, {"inner": "obj"}],
			"something": {
				"?type": "fromdoc"
			}
		}
	} baz end-
} -returnCodes error -result {Expected an integer index or end(-integer)?, got end-}
#>>>
test keys-60.16 {invalid path: subscribed atomic: template string} -body { #<<<
	json keys {
		{
			"foo": "~S:bar",
			"baz":  ["str", 123, 123.4, true, false, null, {"inner": "obj"}],
			"something": {
				"?type": "fromdoc"
			}
		}
	} foo blah
} -returnCodes error -result {Cannot descend into atomic type "string" with path element 2: "blah"}
#>>>
test keys-60.17 {invalid path: subscribed atomic: template number} -body { #<<<
	json keys {
		{
			"foo": "~N:bar",
			"baz":  ["str", 123, 123.4, true, false, null, {"inner": "obj"}],
			"something": {
				"?type": "fromdoc"
			}
		}
	} foo blah
} -returnCodes error -result {Cannot descend into atomic type "string" with path element 2: "blah"}
#>>>
test keys-60.18 {invalid path: subscribed atomic: template boolean} -body { #<<<
	json keys {
		{
			"foo": "~B:bar",
			"baz":  ["str", 123, 123.4, true, false, null, {"inner": "obj"}],
			"something": {
				"?type": "fromdoc"
			}
		}
	} foo blah
} -returnCodes error -result {Cannot descend into atomic type "string" with path element 2: "blah"}
#>>>
test keys-60.19 {invalid path: subscribed atomic: template json doc} -body { #<<<
	json keys {
		{
			"foo": "~J:bar",
			"baz":  ["str", 123, 123.4, true, false, null, {"inner": "obj"}],
			"something": {
				"?type": "fromdoc"
			}
		}
	} foo blah
} -returnCodes error -result {Cannot descend into atomic type "string" with path element 2: "blah"}
#>>>
test keys-60.20 {invalid path: subscribed atomic: template json template} -body { #<<<
	json keys {
		{
			"foo": "~T:bar",
			"baz":  ["str", 123, 123.4, true, false, null, {"inner": "obj"}],
			"something": {
				"?type": "fromdoc"
			}
		}
	} foo blah
} -returnCodes error -result {Cannot descend into atomic type "string" with path element 2: "blah"}
#>>>
test keys-60.21 {invalid path: subscribed atomic: template literal} -body { #<<<
	json keys {
		{
			"foo": "~L:bar",
			"baz":  ["str", 123, 123.4, true, false, null, {"inner": "obj"}],
			"something": {
				"?type": "fromdoc"
			}
		}
	} foo blah
} -returnCodes error -result {Cannot descend into atomic type "string" with path element 2: "blah"}
#>>>
test keys-60.22 {invalid path: subscribed atomic: template invalid} -body { #<<<
	json keys {
		{
			"foo": "~X:bar",
			"baz":  ["str", 123, 123.4, true, false, null, {"inner": "obj"}],
			"something": {
				"?type": "fromdoc"
			}
		}
	} foo blah
} -returnCodes error -result {Cannot descend into atomic type "string" with path element 2: "blah"}
#>>>

test keys-70.1 {Path tail element isn't interpreted as a modifier - no need to escape} -body { #<<<
	json keys {
		{
			"foo": "bar",
			"baz":  ["str", 123, 123.4, true, false, null, {"inner": "obj"}],
			"something": {
				"?type": {"fromdoc": "yes", "also this": "too", "another": null}
			}
		}
	} something ?type
} -result {fromdoc {also this} another}
#>>>

::tcltest::cleanupTests
return

# vim: ft=tcl foldmethod=marker foldmarker=<<<,>>> ts=4 shiftwidth=4


